﻿#include "VertexData.h"

VertexData* VertexData::create()
{
    VertexData* result = new (std::nothrow) VertexData();

    if (result)
    {
        return result;
    }

    return nullptr;
}

size_t VertexData::getVertexStreamCount() const
{
    return _vertexStreams.size();
}

bool VertexData::setStream(std::shared_ptr<VertexBuffer>& buffer, const VertexStreamAttribute& stream)
{
    if (buffer == nullptr) 
    {
        return false;
    }

    auto iter = _vertexStreams.find(stream._semantic);
    if (iter == _vertexStreams.end())
    {
        auto& bufferAttribute = _vertexStreams[stream._semantic];
        bufferAttribute._buffer = buffer;
        bufferAttribute._stream = stream;
    }
    else
    {
        iter->second._stream = stream;
        iter->second._buffer = buffer;
    }

    return true;
}

void VertexData::removeStream(int semantic)
{
    auto iter = _vertexStreams.find(semantic);
    if (iter != _vertexStreams.end())
    {
        _vertexStreams.erase(iter);
    }
}

VertexStreamAttribute* VertexData::getStreamAttribute(int semantic)
{
    auto iter = _vertexStreams.find(semantic);
    if (iter == _vertexStreams.end())
    {
        return nullptr;
    }
    else
    {
        return &iter->second._stream;
    }
}

std::shared_ptr<VertexBuffer>& VertexData::getStreamBuffer(int semantic)
{
    auto iter = _vertexStreams.find(semantic);
    if (iter == _vertexStreams.end()) 
    {
        return std::shared_ptr<VertexBuffer>(nullptr);
    }
    else 
    {
        return iter->second._buffer;
    }
}

VertexData::VertexData()
{
}

VertexData::~VertexData()
{
    _vertexStreams.clear();
}

void VertexData::use()
{
    int lastVBO = -1;

    for (auto& element : _vertexStreams)
    {
        auto vertexStreamAttrib = element.second._stream;
        auto vertexBuffer = element.second._buffer;

        // glBindBuffer()对性能消耗较大,如果不需要则不要调用
        int vbo = vertexBuffer->getVBO();
        if (vbo != lastVBO) 
        {
            glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer->getVBO());
            lastVBO = vbo;
        }

        // 开启顶点数组模式:索引
        glEnableVertexAttribArray(GLuint(vertexStreamAttrib._semantic));

        // 设置:索引、向量元素个数、数值类型、是否规范化、向量之间的跨距、起始位置
        glVertexAttribPointer(GLuint(vertexStreamAttrib._semantic),
            vertexStreamAttrib._size,
            vertexStreamAttrib._type,
            vertexStreamAttrib._normalize,
            vertexBuffer->getSizePerVertex(),
            (GLvoid*)((long)vertexStreamAttrib._offset));
    }
}